﻿using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Microsoft.Extensions.DependencyInjection;
using NLog;
using SocketTool.Dll;
using SocketTool.ViewModels;
using SocketTool.Views;
using System;
using System.IO;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Media;
using Avalonia.ReactiveUI;
using SocketTool.ViewModels.ControlViewModel;
using SocketTool.ViewModels.Protocols;
using SocketTool.ViewModels.TCP;

namespace SocketTool
{
    public partial class App : Application
    {
        private ILogger mLogger;

        #region 字体，避免中文乱码

        private const string mWinFontFamily = "Microsoft YaHei";
        private const string mMacFontFamily = "苹方-简";

        #endregion

        public static Window MainWindow = null;
        
        public override void Initialize()
        {
            AvaloniaXamlLoader.Load(this);

            #region 注册全局异常
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
            TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
            #endregion

            this.mLogger = LogManager.GetCurrentClassLogger();
            
            var connectionHistoryCache = new ConnectionHistoryDll();
            if (!connectionHistoryCache.CheckDbFile(out string connectionError))
            {
                this.mLogger.Error($"Check ConnectionHistory DB File Error : {connectionError}");
                Environment.Exit(Environment.ExitCode);
            }

            var protocolGroupCache = new ProtocolGroupDll();
            if (!protocolGroupCache.CheckDbFile(out string protocolGroupCacheError))
            {
                this.mLogger.Error($"Check ProtocolGroup DB File Error : {protocolGroupCacheError}");
                Environment.Exit(Environment.ExitCode);
            }

            var jsonProtocols = new JsonProtocolsDll();
            if (!jsonProtocols.CheckDbFile(out string jsonProtocolsCacheError))
            {
                this.mLogger.Error($"Check JsonProtocols DB File Error : {jsonProtocolsCacheError}");
                Environment.Exit(Environment.ExitCode);
            }
            GlobalContext.Current.VMLocator = App.Current.Resources["VMLocator"] as ViewModelLocator;
            IServiceCollection serviceCollection = new ServiceCollection();
            serviceCollection.AddSingleton(typeof(ILogger), mLogger);
            serviceCollection.AddSingleton(connectionHistoryCache);
            serviceCollection.AddSingleton(protocolGroupCache);
            serviceCollection.AddSingleton(jsonProtocols);
            
            // serviceCollection.AddHttpClient();
            serviceCollection.RegisterViewModel();

            var provider = serviceCollection.BuildServiceProvider();
            GlobalContext.Current.VMLocator.Initialize(provider);

            //清理日志缓存
            var applicationPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            this.ClearNLog(applicationPath);
        }

        public override void OnFrameworkInitializationCompleted()
        {
            if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
            {
                desktop.MainWindow = new MainWindow
                {
                    DataContext = new MainWindowViewModel(),
                };
            }

            base.OnFrameworkInitializationCompleted();
        }

        private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
        {
            mLogger.Error(e.Exception, "TaskScheduler_UnobservedTaskException");

            var stringBuilder = new StringBuilder();
            stringBuilder.AppendLine("TaskScheduler_UnobservedTaskException");
            stringBuilder.AppendLine($"DateTime {DateTime.Now}");
            stringBuilder.AppendLine($"ErrorMessage {e.Exception.Message}");
            stringBuilder.AppendLine($"InnerErrorMessage {e.Exception.InnerException?.Message}");
            stringBuilder.AppendLine($"StackTrace {e.Exception.StackTrace}");
            stringBuilder.AppendLine($"InnerStackTrace {e.Exception.InnerException?.StackTrace}");
            var errorMsg = stringBuilder.ToString();
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine(errorMsg);
            Console.ResetColor();
            e.SetObserved();
        }

        private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            if (e.ExceptionObject is Exception)
            {
                mLogger.Error((Exception)e.ExceptionObject, "CurrentDomain_UnhandledException");
            }

            var sbEx = new StringBuilder();
            sbEx.AppendLine("CurrentDomain_UnhandledException");
            sbEx.AppendLine($"DateTime {DateTime.Now}");
            if (e.ExceptionObject is Exception)
            {
                sbEx.AppendLine(((Exception)e.ExceptionObject).Message);
            }
            else
            {
                sbEx.AppendLine(e.ExceptionObject != null ? e.ExceptionObject.ToString() : null);
            }
            var errorMsg = sbEx.ToString();
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine(errorMsg);
            Console.ResetColor();
        }

        /// <summary>
        /// 清理NLog日志
        /// </summary>
        private void ClearNLog(string applicationPath)
        {
            try
            {
                DateTime deleteTime = DateTime.Now.Date.AddDays(-3);
                var logFolderPath = Path.Combine(applicationPath, "logs");
                if (!Directory.Exists(logFolderPath))
                    return;
                var logList = new DirectoryInfo(logFolderPath).GetFiles("*", SearchOption.AllDirectories);
                foreach (var log in logList)
                {
                    if (log.CreationTime < deleteTime)
                    {
                        log.Delete();
                    }
                }
            }
            catch (Exception ex)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine($"ClearNLog {ex.Message}");
                Console.ResetColor();
            }
        }
    }

    public static class ServiceCollectionExtention
    {
        public static void RegisterViewModel(this IServiceCollection serviceCollection)
        {
            serviceCollection.AddTransient<ReqMessageParamViewModel>();
            
            serviceCollection.AddSingleton<MainWindowViewModel>();
            serviceCollection.AddSingleton<GlobalViewModel>();
            serviceCollection.AddSingleton<TCPClientViewModel>();



            serviceCollection.AddSingleton<ProtocolManageViewModel>();
        }
    }
}